import { BlockNoteView } from "@blocknote/mantine";
import { FilePanelController, SuggestionMenuController, getDefaultReactSlashMenuItems, useCreateBlockNote } from "@blocknote/react";
import { main } from "@model";
import "@blocknote/core/fonts/inter.css";
import "@blocknote/mantine/style.css";
import { useEffect, useRef, useState } from "react";
import { SaveDocument, TagList } from "@app";
import { ClipImage } from "@runtimeExt";
import { Affix, Button, Flex, Select, SelectProps, Space, notification } from "antd";
import { useNavigate } from "react-router-dom";
import { blockSchema } from "./blockNoteCustom/schema";
import { filterSuggestionItems, insertOrUpdateBlock } from "@blocknote/core";
import { RiAlertFill, RiCodeSSlashFill } from "react-icons/ri";
import { SiMermaid } from "react-icons/si";
import { CustomFilePanelController } from "./blockNoteCustom/filePanelController/CustomFilePanelController";
import { DogInTheManger } from "@/config/TitleBarHiddenInset";
import { locales } from "@blocknote/core"
// import { ServerBlockNoteEditor } from "@blocknote/server-util"
import { locale } from "moment";
import { useDebounce } from "ahooks";
import { debounce } from "@/utils/debounce";
// import { ServerBlockNoteEditor } from "@blocknote/server-util";

// Slash menu item to insert an Alert block
const insertAlert = (editor: any) => ({
  title: "Alert",
  onItemClick: () => {
    insertOrUpdateBlock(editor, {
      type: "alert",
    });
  },
  aliases: [
    "alert",
    "notification",
    "emphasize",
    "warning",
    "error",
    "info",
    "success",
  ],
  group: "Other",
  icon: <RiAlertFill />,
})

const insertCodeBlock = (editor: typeof blockSchema.BlockNoteEditor) => ({
  title: "Code",
  onItemClick: () => {
    insertOrUpdateBlock(editor, {
      type: "codeBlock",
    })
  },
  group: "Other",
  icon: <RiCodeSSlashFill />,
})

const insertMermaidBlock = (editor: typeof blockSchema.BlockNoteEditor) => ({
  title: 'Mermaid',
  onItemClick: () => {
    insertOrUpdateBlock(editor, {
      type: 'mermaid'
    })
  },
  group: "Chart",
  icon: <SiMermaid />,
})

const insertDraw = (editor: typeof blockSchema.BlockNoteEditor) => ({
  title: 'draw',
  onItemClick: () => {
    insertOrUpdateBlock(editor, {
      type: 'draw'
    })
  },
  group: 'Chart',
  icon: <SiMermaid />,
})

export default function DataToBlockNoteView(props: {
  note: main.Note
}) {
  const navigate = useNavigate()

  const parentRoot = useRef<HTMLDivElement | null>(null)
  const blockView = useRef<HTMLDivElement | null>(null)
  const note = useRef(new main.Note({
    ...props.note
  }))

  const [options, setOptions] = useState([] as SelectProps['options'])
  const [selectedTag, setSelectedTag] = useState([] as string[])

  const editor = useCreateBlockNote({
    schema: blockSchema,
    dictionary: locales.zh,
    initialContent: JSON.parse(props.note.content),
  })

  const debounceSave = debounce(() => {
    note.current.content = JSON.stringify(editor.document)
    SaveDocument(note.current).then((n) => {
      note.current.id = n.id
      note.current.createTime = n.createTime
    }).catch((err) => {
      notification.error({
        message: "保存失败",
        description: err,
        placement: 'bottomRight'
      })
    })
  }, 1000)

  // init
  useEffect(() => {
    TagList().then(tags => {
      const ptags = tags.map(tag => {
        return {
          value: tag.name,
          label: tag.name,
        }
      })
      setOptions(ptags)
    })
    if (note.current.tags != null) {
      const selected = note.current.tags.map(tag => tag.name)
      setSelectedTag(selected)
    }
  }, [])

  // key map
  useEffect(() => {
    const shortcutKey = (event: KeyboardEvent) => {
      if ((event.metaKey || event.ctrlKey )&& event.key == 's') {
        event.preventDefault()
        save()
      }

      if ((event.metaKey || event.ctrlKey) && event.key == 'w') {
        event.preventDefault()
        navigate(-1)
      }

    }

    if (parentRoot.current) {
      parentRoot.current.addEventListener('keydown', shortcutKey)
    }

    return () => {
      if (parentRoot.current) {
        parentRoot.current.removeEventListener('keydown', shortcutKey)
      }
    }

  }, [parentRoot])

  // paste
  useEffect(() => {
    const pasteHandler = (event: ClipboardEvent) => {
      event.preventDefault()
      const clipboardData = event.clipboardData
      if (clipboardData) {
        for (let i = 0; i < clipboardData.items.length; i++) {
          const item = clipboardData.items[i];
          if (item.kind === 'file' && item.type === 'image/png') {
            ClipImage().then((filename: string) => {
              insertImageBlock(filename)
            }).catch(e => {
              notification.error({
                message: '粘贴失败!',
                description: e,
                placement: 'bottomRight',
              })
            })
          }
        }
      }
    }

    if (blockView.current) {
      blockView.current.addEventListener('paste', pasteHandler)
    }

    return () => {
      if (blockView.current) {
        blockView.current.removeEventListener('paste', pasteHandler)
      }
    }
  }, [blockView])

  const insertImageBlock = (filename: string) => {
    const blockIdentifer = editor.getTextCursorPosition().block
    const block = editor.getBlock(blockIdentifer)
    if (!block) {
      return
    }

    if (block.type === 'paragraph' && (block.content == null || (block.content as []).length === 0)) {
      editor.updateBlock(block, {
        type: 'image',
        props: {
          name: filename,
          url: `/file/${filename}`,
        },
      })
    } else {
      editor.insertBlocks([{
        type: 'image',
        props: {
          name: filename,
          url: `/file/${filename}`,
        },
      }], block, 'after')
    }

  }

  const save = () => {
    note.current.content = JSON.stringify(editor.document)
    SaveDocument(note.current).then((n) => {
      note.current.id = n.id
      note.current.createTime = n.createTime
    }).then(() => {
      notification.success({
        message: "保存成功",
        placement: 'bottomRight'
      })
    }).catch((err) => {
      notification.error({
        message: "保存失败",
        description: err,
        placement: 'bottomRight'
      })
    })
  }

  editor.onEditorContentChange(() => {
    debounceSave()
    if (note.current.id == undefined || note.current.id == 0) {
      return
    }
    note.current.content = JSON.stringify(editor.document)

    // SaveDocument(note.current)
    debounceSave()
  })

  const onTagChange = (value: string[]) => {
    setSelectedTag(value)
    const tags = value.map(tag => new main.Tag({ name: tag }))
    note.current.tags = tags
  }

  const exportDocument = async () => {
    // const blocks = editor.document
    // const serverSideEditor = ServerBlockNoteEditor.create({
    //   schema: blockSchema,
    // });
    // const html = await serverSideEditor.blocksToFullHTML(blocks);
    editor.blocksToFullHTML(editor.document).then(html => {
      console.log(html)
    })
  }

  return <div ref={parentRoot}>
    <Affix>
      <Flex style={{
        '--wails-draggable': 'drag',
        padding: '5px 0 5px 0',
        backgroundColor: '#FFF',
      } as React.CSSProperties} justify="space-between">
        <Space>
          <DogInTheManger />
          <Button onClick={() => navigate(-1)} >返回</Button>
          <Button type="primary" onClick={save} >保存</Button>
        </Space>
        <Space>
          <Button onClick={exportDocument}>导出(TODO)</Button>
        </Space>
      </Flex>
    </Affix>

    <Select
      mode="tags"
      value={selectedTag}
      style={{
        width: '100%',
        borderBottom: '1px solid #eee'
      }}
      tokenSeparators={[',']}
      options={options}
      onChange={onTagChange}
      placeholder={'输入 tags'}
      variant='borderless'
    />

    <div ref={blockView}>
      <BlockNoteView
        style={{
          minHeight: '500px'
        }}
        editor={editor}
        editable={true}
        slashMenu={false}
        filePanel={false}
      >
        <SuggestionMenuController
          triggerCharacter="/"
          getItems={
            async (query) =>
              filterSuggestionItems(
                [
                  ...getDefaultReactSlashMenuItems(editor),
                  insertCodeBlock(editor),
                  insertAlert(editor),
                  insertMermaidBlock(editor),
                  insertDraw(editor),
                ],
                query
              )
          }
        />
        <FilePanelController filePanel={CustomFilePanelController} />
      </BlockNoteView >
    </div>
    <div style={{ height: 300 }}></div>
  </div>

}

